﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TwlNS {
	public partial class Canvas : Form {
		private static List<Canvas> instances = new List<Canvas>();
		public static void Repaint() {
			foreach (var canvas in instances) {
				canvas.Refresh();
			}
		}

		private readonly double CANVAS_WIDTH = 800.0;
		private readonly double CANVAS_HEIGHT = 800.0;
		public static bool DisplayAllLinks { get; set; }
		public static bool DisplayPossibleParentLinks { get; set; }
		public static bool DisplayNoneSinkedParentLinks { get; set; }
		public static bool DisplaySinkedParentLinks { get; set; }

		private Environment _Env;
		public Environment Env {
			get { return _Env; }
		}
		private double _scale;
		private bool _hori_env = true;

		public Canvas(Environment env) {
			InitializeEnv(env);
			InitializeComponent();
			instances.Add(this);

		}
		private void Canvas_FormClosing(object sender, FormClosingEventArgs e) {
			instances.Remove(this);
		}

		private void InitializeEnv(Environment env) {
			_Env = env;

			//Setup scaling
			double width_ratio = Env.Width / CANVAS_WIDTH;
			double height_ratio = Env.Height / CANVAS_HEIGHT;
			_scale = width_ratio;
			if (height_ratio > width_ratio) {
				_scale = height_ratio;
				_hori_env = false;
			}
		}

		/*
		 * Center the scaled env
		 */
		private Point SanitizedPoint(Coord c) {
			int x = (int)(c.X / _scale);
			int y = (int)(c.Y / _scale);
			if (_hori_env) {
				int offset = (int)((CANVAS_HEIGHT - Env.Height / _scale) / 2);
				y += offset;
			} else {
				int offset = (int)((CANVAS_WIDTH - Env.Width / _scale) / 2);
				x += offset;
			}
			return new Point(x, y);
		}

		protected override void OnPaint(PaintEventArgs e) {
			Graphics g = e.Graphics;
			//Draw neighbor connectivity
			if (DisplayAllLinks) {
				foreach (Node n in Env.Nodes) {
					Point p = SanitizedPoint(n.Location);
					foreach (var neighbor in n.RadioRangeNeighbor) {
						//Only paint it once per pair
						if (neighbor.Id < n.Id) {
							using (Pen pen = new Pen(Color.White, 1)) {
								Point p2 = SanitizedPoint(neighbor.Location);
								g.DrawLine(pen, p.X, p.Y, p2.X, p2.Y);
							}
						}
					}
				}
			}
			//Draw possible parent connectivity
			if (DisplayPossibleParentLinks) {
				foreach (Node n in Env.Nodes) {
					Point p = SanitizedPoint(n.Location);
					foreach (var neighbor in n.PossibleParents) {
						using (Pen pen = new Pen(Color.Blue, 1)) {
							Point p2 = SanitizedPoint(neighbor.Location);
							g.DrawLine(pen, p.X, p.Y, p2.X, p2.Y);
						}
					}
				}
			}
			//Draw actual parent node connectivity
			foreach (Node n in Env.Nodes) {
				if(!DisplayNoneSinkedParentLinks && !n.Sinked)
					continue;
				if(!DisplaySinkedParentLinks && n.Sinked)
					continue;
				Color color = n.Sinked?Color.GreenYellow: Color.LightPink;
				Point p = SanitizedPoint(n.Location);
				foreach (var parentNode in n.ParentNodes){
					Point p2 = SanitizedPoint(parentNode.Location);
					using (Pen pen = new Pen(color, 1)) {
						g.DrawLine(pen, p.X, p.Y, p2.X, p2.Y);
					}
				}/*
				if (n.ParentNodes != null) {
					Point p2 = SanitizedPoint(n.ParentNodes.Location);
					using (Pen pen = new Pen(color , 1)) {
						g.DrawLine(pen, p.X, p.Y, p2.X, p2.Y);
					}
				}*/
			}
			foreach (Node n in Env.Nodes) {
				Point p = SanitizedPoint(n.Location);
				int x = p.X;
				int y = p.Y;
				if (n is SinkNode) {
					using (Pen pen = new Pen(Color.Green, 2)) {
						g.FillRectangle(new SolidBrush(Color.White), x - 2, y - 2, 9, 9);
						g.DrawRectangle(pen, x, y, 5, 5);
					}
				} else {
					Color color = n.PossibleParents.Count == 0 ? Color.Red :
						!n.Sinked ? Color.Red : Color.Orange;
					Color fillColor = n.PossibleParents.Count == 0 ? Color.Red :
						!n.Sinked ? Color.Red : Color.White;
					using (Pen pen = new Pen(color, 2)) {
						g.FillRectangle(new SolidBrush(fillColor), x - 2, y - 2, 7, 7);
						g.DrawRectangle(pen, x, y, 3, 3);
					}
				}

			}
			//g.DrawRectangle(new Pen(Color.Chartreuse, 2), 364, 164, 2, 2);
			base.OnPaint(e);
		}


	}
}